class Burger {
  late double _size;
  late bool _cheese;
  late bool _beef;
  late bool _lettuce;
  late bool _tomato;

  // Not good:  Burger(this._size, this._cheese, this._beef, this._lettuce, this._tomato);
  // 把所有的属性都挤在了构造参数里

  //good： 将实例复杂属性配置下放到builder中，由builder来处理
  Burger(BurgerBuilder builder) {
    _size = builder._size;
    _cheese = builder._cheese;
    _beef = builder._beef;
    _lettuce = builder._lettuce;
    _tomato = builder._tomato;
  }

  String content() => """
  Your Burger size: $_size,
  Cheese: $_cheese,
  Beef: $_beef,
  Lettuce: $_lettuce,
  Tomato: $_tomato.
  """;
}

// 利用 Builder 中方法來多步配置实例，并通过 build 方法构建目标实体
// 配置方法返回 builder 本身（this）来连续配置属性
// BurgerBuilder().addCheese().addBeef().build();
class BurgerBuilder {
  final double _size;
  bool _cheese = false;
  bool _beef = false;
  bool _lettuce = false;
  bool _tomato = false;

  BurgerBuilder(this._size);

  BurgerBuilder addCheese() {
    _cheese = true;
    return this;
  }

  BurgerBuilder addBeef() {
    _beef = true;
    return this;
  }

  BurgerBuilder addLettuce() {
    _lettuce = true;
    return this;
  }

  BurgerBuilder addTomato() {
    _tomato = true;
    return this;
  }

  Burger build() => Burger(this);
}

/*
建造者

目的
将复杂的实体拆开成每个零件，像游戏角色一样，有职业、性别、头发等等。

何时使用
当一个实体有很多分部，并且想避免"伸缩建构"时。 Character(name, hair, profession, ......) 
全部挤在一个 constructor 中。 跟 Factory 不同的是，Factory 通常一步就可以生产，而 Builder 需要多步建构。
 */
void main(List<String> args) {
  var noLettuceBurger =
      BurgerBuilder(15).addBeef().addCheese().addTomato().build();

  print(noLettuceBurger.content());

  // Builder👇👇👇
  // Your Burger size: 15.0,
  // Cheese: true,
  // Beef: true,
  // Lettuce: false,
  // Tomato: true.
}
